package com.example.common.global;

import com.alibaba.fastjson.JSON;
import com.example.common.util.IpUtil;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.Arrays;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;

/**
 * @author Aaron
 * @since 2021/3/31 14:59
 * <p>描述：</p>
 */
@Aspect
@Component
public class ControllerLogAop {
    private final static Logger logger = LoggerFactory.getLogger(ControllerLogAop.class);

    /**
     * 指定切点 匹配指定包及其子包下的所有类的所有方法
     *
     * @author wangl
     */
    @Pointcut("execution(public * com.example.*.controller.*.*(..))")
    public void webLog() {
    }

    /**
     * 环绕通知, 环绕增强，相当于MethodInterceptor
     *
     * @return Object
     * @author wangl
     */
    @Around("webLog()")
    public Object around(ProceedingJoinPoint joinPoint) throws Throwable {
        long start = System.currentTimeMillis();

        // 方法参数内容
        List<Object> logArgs = Arrays.stream(joinPoint.getArgs()).filter(
                t -> !(t instanceof HttpServletRequest || t instanceof HttpServletResponse || t instanceof MultipartFile))
                .collect(Collectors.toList());
        // 接收到请求，记录请求内容
        ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        HttpServletRequest request = Objects.requireNonNull(attributes).getRequest();

        logger.info("Request URL    : {}", request.getRequestURL().toString());
        logger.info("Request Method : {}", request.getMethod());
        logger.info("token          : {}", request.getHeader("token"));
        logger.info("Host           : {}", IpUtil.getIp(request));
        logger.info("Class Name     : {}", joinPoint.getSignature().getDeclaringTypeName());
        logger.info("Method Name    : {}", joinPoint.getSignature().getName());
        logger.info("Params Name    : {}", Arrays.toString(((MethodSignature) joinPoint.getSignature()).getParameterNames()));
        logger.info("Params Value   : {}", JSON.toJSONString(logArgs));

        Object result = joinPoint.proceed();

        logger.info("Time Consuming : {} ms", System.currentTimeMillis() - start);

        return result;
    }

}
